package com.chaoxing.ai.speech.utils;

import java.io.*;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.alibaba.fastjson.JSONObject;

public class FFmpegUtil {

    static Log logger = LogFactory.getLog(FFmpegUtil.class);

    public static int ffprobeGetVideoTime(String ffprobePath, String filePath) {
        String cmd = ffprobePath + " -v quiet -print_format json -show_format -i " + filePath;
        System.out.println(cmd);
        BufferedReader inBr = null;
        try {
            Runtime run = Runtime.getRuntime();
            Process p = run.exec(cmd);
            inBr = new BufferedReader(new InputStreamReader(p.getInputStream(), "utf-8"));
            StringBuffer sb = new StringBuffer();
            String lineStr;
            while ((lineStr = inBr.readLine()) != null) {
                sb.append(lineStr);
            }
            if (p.waitFor() != 0) {
                if (p.exitValue() == 1) {
                    logger.error("命令执行失败!");
                }
            }
            return analyseInfo(sb.toString());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (inBr != null) {
                try {
                    inBr.close();
                } catch (IOException e) {
                    logger.error(e);
                }
            }
        }
        return 0;
    }

    private static int analyseInfo(String json) throws IOException {
        if (json != null && !json.equals("")) {
            JSONObject jsons = JSONObject.parseObject(json);
            if (jsons.containsKey("format")) {
                JSONObject formatjson = jsons.getJSONObject("format");
                if (formatjson.containsKey("duration")) {
                    double time = formatjson.getDouble("duration");
                    int times = (int) time;
                    return times;
                    //BigDecimal bd=new BigDecimal(time).setScale(0, BigDecimal.ROUND_HALF_UP);//四舍五入把double转化int整型，0.5进一，小于0.5不进一
                    //return  Integer.parseInt(bd.toString());
                }
            }
        }
        return 0;
    }

    /**
     * 获取本地视频总时间
     *
     * @param
     * @param ffmpeg_path ffmpeg路径
     * @return
     */
    public static int ffmpegGetVideoTime(String video_path, String ffmpeg_path) {
        List<String> commands = new ArrayList<String>();
        commands.add(ffmpeg_path);
        commands.add("-i");
        commands.add(video_path);
        try {
            ProcessBuilder builder = new ProcessBuilder();
            builder.command(commands);
            final Process p = builder.start();
            // 从输入流中读取视频信息

            //从输入流中读取视频信息
            BufferedReader br = new BufferedReader(new InputStreamReader(p.getErrorStream()));
            StringBuffer sb = new StringBuffer();
            String line = "";
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
            br.close();
            //从视频信息中解析时长
            String regexDuration = "Duration: (.*?), start: (.*?), bitrate: (\\d*) kb\\/s";
            Pattern pattern = Pattern.compile(regexDuration);
            Matcher m = pattern.matcher(sb.toString());
            if (m.find()) {
                int time = getTimelen(m.group(1));
                System.out.println(video_path + ",视频时长：" + time + ",开始时间：" + m.group(2) + ",比特率：" + m.group(3) + "kb/s");
                return time;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return 0;
    }

    // 格式:"00:00:10.68"
    private static int getTimelen(String timelen) {
        int min = 0;
        String strs[] = timelen.split(":");
        if (strs[0].compareTo("0") > 0) {
            min += Integer.valueOf(strs[0]) * 60 * 60;// 秒
        }
        if (strs[1].compareTo("0") > 0) {
            min += Integer.valueOf(strs[1]) * 60;
        }
        if (strs[2].compareTo("0") > 0) {
            min += Math.round(Float.valueOf(strs[2]));
        }
        return min;
    }

    /**
     * 此方法封装的为利用FFmpeg对M4a，mp3，amr文件至Wav文件的转换方法
     * webroot FFmpeg的bin路径,sourcePath为 M4a文件地址, targetPath为转换后的文件地址
     *
     * @param webroot
     * @param sourcePath
     * @param targetPath
     * @return
     */
    public static String FfmpegToWav(String webroot, String sourcePath, String targetPath) {
        Runtime run = null;
        try {
            run = Runtime.getRuntime();
            long start = System.currentTimeMillis();
            System.out.println(new File(webroot).getAbsolutePath());
            //执行ffmpeg.exe,前面是ffmpeg.exe的地址，中间是需要转换的文件地址，后面是转换后的文件地址。-i是转换方式，意思是可编码解码，mp3编码方式采用的是libmp3lame
            Process p = run.exec(new File(webroot).getAbsolutePath() + "/ffmpeg -y -i " + sourcePath + " -acodec pcm_s16le -ac 2 -ar 8000 " + targetPath);
            p.getOutputStream().close();
            p.getInputStream().close();
            p.getErrorStream().close();
            p.waitFor();
            long end = System.currentTimeMillis();
            System.out.println(sourcePath + " convert success, costs:" + (end - start) + "ms");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            run.freeMemory();
        }
        File file = new File(targetPath);
        if(file.isFile()){
           return "转换成功";
        }
        return "转换失败";
    }

    /**
     * 此方法封装的为利用FFmpeg对M4a,wav,amr文件至Pcm文件的转换方法
     * webroot FFmpeg的bin路径,sourcePath为 M4a文件地址, targetPath为转换后的文件地址
     *
     * @param webroot
     * @param sourcePath
     * @param targetPath
     * @return
     */
    public static String FfmpegToMp3(String webroot, String sourcePath, String targetPath) {
        Runtime run = null;
        try {
            run = Runtime.getRuntime();
            long start = System.currentTimeMillis();
            System.out.println(new File(webroot).getAbsolutePath());
            //执行ffmpeg.exe,前面是ffmpeg.exe的地址，中间是需要转换的文件地址，后面是转换后的文件地址。-i是转换方式，意思是可编码解码，mp3编码方式采用的是libmp3lame
            Process p = run.exec(new File(webroot).getAbsolutePath() + "/ffmpeg -i  " + sourcePath + " -y -acodec libmp3lame -aq 0 " + targetPath );
            p.getOutputStream().close();
            p.getInputStream().close();
            p.getErrorStream().close();
            p.waitFor();
            long end = System.currentTimeMillis();
            System.out.println(sourcePath + " convert success, costs:" + (end - start) + "ms");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            run.freeMemory();
        }
        return "1";
    }

    /**
     * 此方法封装的为利用FFmpeg对Wav,mp3,m4a,am4文件pcm文件的转换方法
     * webroot FFmpeg的bin路径,sourcePath为 Wav文件地址, targetPath为转换后的文件地址
     *
     * @param webroot
     * @param sourcePath
     * @param targetPath
     * @return
     */
    public static String FfmpegTopcm(String webroot, String sourcePath, String targetPath) {
        Runtime run = null;
        try {
            run = Runtime.getRuntime();
            long start = System.currentTimeMillis();
            System.out.println(new File(webroot).getAbsolutePath());
            Process p = run.exec(new File(webroot).getAbsolutePath() + "/ffmpeg -y -i " + sourcePath + " -acodec pcm_s16le -f s16le -ac 1 -ar 16000 " + targetPath);
            p.getOutputStream().close();
            p.getInputStream().close();
            p.getErrorStream().close();
            p.waitFor();
            long end = System.currentTimeMillis();
            System.out.println(sourcePath + " convert success, costs:" + (end - start) + "ms");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            run.freeMemory();
        }
        return "1";
    }
    /**
     * 此方法封装的为利用FFmpeg对Wav,mp3,m4a,am4文件pcm文件的转换方法
     * webroot FFmpeg的bin路径,sourcePath为 Wav文件地址, targetPath为转换后的文件地址
     *
     * @param webroot
     * @param sourcePath
     * @param targetPath
     * @return
     */
    public static String FfmpegToM4a(String webroot, String sourcePath, String targetPath) {
        Runtime run = null;
        try {
            run = Runtime.getRuntime();
            long start = System.currentTimeMillis();
            System.out.println(new File(webroot).getAbsolutePath());
            Process p = run.exec(new File(webroot).getAbsolutePath() + "/ffmpeg -i " + sourcePath + " -acodec libfdk_aac -profile:a aac_he_v2 -vbr 5 " + targetPath);
            p.getOutputStream().close();
            p.getInputStream().close();
            p.getErrorStream().close();
            p.waitFor();
            long end = System.currentTimeMillis();
            System.out.println(sourcePath + " convert success, costs:" + (end - start) + "ms");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            run.freeMemory();
        }
        return "1";
    }
    public static void main(String[] args) {
        long startime = System.currentTimeMillis();
        System.out.println(ffmpegGetVideoTime("https://s1.ananas.chaoxing.com/video/25/a1/2e/baa1e327b9e03769fe56252d2f92f643/sd.mp4?at_=1575549940165&ak_=04ba9e39a1f65ad6ee7f4d0031f6c627&ad_=d254216e35b6affdd6f906a0c1f88ae7", "D:\\ffmpeg-3.3.1-win64-static\\bin\\ffmpeg.exe"));
        System.out.println(ffmpegGetVideoTime("http://d0.ananas.chaoxing.com/download/baa1e327b9e03769fe56252d2f92f643", "D:\\ffmpeg-3.3.1-win64-static\\bin\\ffmpeg.exe"));
        long endtime = System.currentTimeMillis();
        long time = endtime - startime;
        System.out.println("ffmpegGetVideoTime所用时间：" + time);
        long startime2 = System.currentTimeMillis();
        System.out.println(ffprobeGetVideoTime("D:\\ffmpeg-3.3.1-win64-static\\bin\\ffprobe.exe", "http://d0.ananas.chaoxing.com/download/baa1e327b9e03769fe56252d2f92f643"));
        long time2 = System.currentTimeMillis() - startime2;
        System.out.println("ffmpegGetVideoTime所用时间：" + time2);
        String webroot = "E:\\ffmpeg\\ffmpeg\\bin";  //ffmpeg安装路径
        String sourcePath = "E:\\api-speeh\\ffmpeguser\\demo.pcm";
        String targetPath = "E:\\api-speeh\\ffmpeguser\\demo.m4a";
        //ffmpeg m4a至wav测试
        //FfmpegTopcm(webroot,sourcePath,targetPath);//成功
        // FfmpegToMp3(webroot,sourcePath,targetPath);//成功 但pcm-》MP3不可用
        //FfmpegToWav(webroot,sourcePath,targetPath);//成功 但pcm->wav 不可用
        File file = new File(targetPath);
        if(file.isFile()){
            System.out.println(true);
        }else{
            System.out.println(false);
        }


    }

}
